#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>

// 定义 EXT2 超级块的结构
struct ext2_super_block {
    uint32_t s_log_block_size; // 数据块大小的指数
    uint32_t s_blocks_count;   // 总块数
    // 其他超级块字段...
};

// 定义 EXT2 组描述符表的结构
struct ext2_group_desc {
    uint32_t bg_block_bitmap;    // 数据块位图的块号
    uint32_t bg_inode_bitmap;    // inode 位图的块号
    uint32_t bg_inode_table;     // inode 表的块号
    // 其他组描述符表字段...
};

// 定义 EXT2 inode 表项的结构
struct ext2_inode {
    uint16_t i_mode;  // 文件类型和权限
    uint32_t i_size;  // 文件大小
    // 其他 inode 表项字段...
};

int main() {
    const char* mount_path = "/mnt/ext2";  // 挂载点路径

    int fd = open(mount_path, O_RDONLY);

    if (fd == -1) {
        perror("Failed to open mount point");
        return 1;
    }

    // 读取超级块
    struct ext2_super_block superblock;
//    fseek(file, 1024, SEEK_SET);  // 根据实际情况设置超级块的偏移
//    fread(&superblock, sizeof(superblock), 1, file);
    lseek(fd, 1024, SEEK_SET);  // 超级块通常位于文件系统开头
    read(fd, &superblock, sizeof(superblock));

    // 根据 s_log_block_size 计算 block_size
    uint32_t block_size = 1024 << superblock.s_log_block_size;

    // 读取组描述符表
    struct ext2_group_desc group_desc;
//    fseek(file, 1024 + block_size, SEEK_SET);  // 根据实际情况设置组描述符表的偏移
//    fread(&group_desc, sizeof(group_desc), 1, file);
    lseek(fd, 1024 + block_size, SEEK_SET);  // 组描述符表通常位于超级块之后
    read(fd, &group_desc, sizeof(group_desc));

    // 读取数据块位图
//    fseek(file, group_desc.bg_block_bitmap * block_size, SEEK_SET);
    lseek(fd, group_desc.bg_block_bitmap * block_size, SEEK_SET); 
    uint8_t *block_bitmap = (uint8_t *)malloc(block_size);
    read(fd, block_bitmap,  block_size);
//    fread(block_bitmap, block_size, 1, file);

    // 读取 inode 位图
//    fseek(file, group_desc.bg_inode_bitmap * block_size, SEEK_SET);
    lseek(fd, group_desc.bg_inode_bitmap * block_size, SEEK_SET); 
    uint8_t *inode_bitmap = (uint8_t *)malloc(block_size);
    read(fd, inode_bitmap,  block_size);
//    fread(inode_bitmap, block_size, 1, file);

    // 读取 inode 表项
//    fseek(file, group_desc.bg_inode_table * block_size, SEEK_SET);
    lseek(fd, group_desc.bg_inode_table * block_size, SEEK_SET); 
    struct ext2_inode inode;
    read(fd, &inode, sizeof(inode));
//    fread(&inode, sizeof(inode), 1, file);

    // 关闭文件
      close(fd);

    // 打印信息
    printf("Block Size: %u bytes\n", block_size);
    printf("Block Bitmap Block: %u\n", group_desc.bg_block_bitmap);
    printf("Inode Bitmap Block: %u\n", group_desc.bg_inode_bitmap);
    printf("Inode Table Block: %u\n", group_desc.bg_inode_table);

    printf("Block Bitmap:\n");
    for (int i = 0; i < 10;i++) {
        for (int bit = 0; bit < 8; bit++) {
            if (block_bitmap[i] & (1 << bit)) {
                printf("Block %d is in use\n", i * 8 + bit);
            } else {
                printf("Block %d is free\n", i * 8 + bit);
            }
        }
    }

    printf("Inode Bitmap:\n");
    for (int i = 0; i < 10; i++) {
        for (int bit = 0; bit < 8; bit++) {
            if (inode_bitmap[i] & (1 << bit)) {
                printf("Inode %d is in use\n", i * 8 + bit);
            } else {
                printf("Inode %d is free\n", i * 8 + bit);
            }
        }
    }

    printf("Inode Information:\n");
    printf("File Mode: 0x%x\n", inode.i_mode);
    printf("File Size: %u bytes\n", inode.i_size);
    // 解析其他 inode 表项字段...

    free(block_bitmap);
    free(inode_bitmap);

    return 0;
}
